package com.mall.b2c.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.mall.b2c.dao.RefundDao;
import com.mall.b2c.domain.member.MemberDomain;
import com.mall.b2c.domain.order.OrderDomain;
import com.mall.b2c.domain.order.OrderItemDomain;
import com.mall.b2c.domain.order.OrderLogDomain;
import com.mall.b2c.domain.order.RefundDomain;
import com.mall.b2c.domain.order.RefundLogDomain;
import com.mall.b2c.enums.LogType;
import com.mall.b2c.enums.OrderStatus;
import com.mall.b2c.enums.RefundStatus;
import com.mall.b2c.service.MemberService;
import com.mall.b2c.service.OrderItemService;
import com.mall.b2c.service.OrderLogService;
import com.mall.b2c.service.OrderService;
import com.mall.b2c.service.RefundLogService;
import com.mall.b2c.service.RefundService;
import com.mall.b2c.util.SerialNumberUtil;
import com.mall.common.domain.AreaDomain;
import com.mall.common.exception.NoticeException;
import com.mall.common.hibernate.Finder;
import com.mall.common.service.AreaService;
import com.mall.common.service.impl.BaseServiceImpl;


/**
 * Service实现类 - 退款单
 * @author 
 */
@Service("b2cRefundService")
@Transactional
public class RefundServiceImpl extends BaseServiceImpl<RefundDomain, Long> implements RefundService {
	@Resource private OrderItemService orderItemService;
	@Resource private AreaService areaService;
	@Resource private RefundLogService refundLogService;
	@Resource private MemberService memberService;
	@Resource private OrderService orderService;
	@Resource private OrderLogService orderLogService;
	
	@Resource
	public void setBaseDao(RefundDao refundDao) { 
		super.setBaseDao(refundDao); 
	}

	@Override
	public RefundDomain getRefund(String refundNo, Long memberId) {
		Finder finder = Finder.create("select bean.refund from OrderItemDomain bean where bean.refund.refundNo=:refundNo and bean.order.member.id=:memberId");
		finder.setParam("refundNo", refundNo);
		finder.setParam("memberId", memberId);
		Object obj = finder.findUniqueByHQL();
		if(obj == null){
			throw new NoticeException("退款记录不存在");
		}
		return (RefundDomain) obj;
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public String applyRefund(Long itemId, Integer quantity, Boolean isChange, String consignee, 
			Long areaId, String address, String contact, String remark, Long memberId) {
		String areaName = null;
		Finder finder = Finder.create("from OrderItemDomain bean where bean.id =:itemId and bean.order.member.id=:memberId");
		finder.setParam("itemId", itemId);
		finder.setParam("memberId", memberId);
		Object obj = finder.findUniqueByHQL();
		if(obj == null){
			throw new NoticeException(isChange?"换货商品不存在":"退货商品不存在");
		}
		OrderItemDomain orderItem = (OrderItemDomain) obj;
		
		if(orderItem.getQuantity() < quantity){
			throw new NoticeException(isChange?"换货数量不正确":"退货数量不存在");
		}
		
		OrderDomain order = orderItem.getOrder();
		if(order.getOrderStatus() != OrderStatus.waitSellerSendGoods
				&& order.getOrderStatus() != OrderStatus.tradeFinished){
			throw new NoticeException("订单状态不正确");
		}
		
		if(isChange){
			if(order.getOrderStatus() == OrderStatus.waitSellerSendGoods){
				throw new NoticeException("订单未发货，无法申请换货");
			}
			if(areaId == null){
				throw new NoticeException("收货地址地区不正确");
			}
			AreaDomain area = areaService.find(areaId);
			if(area == null){
				throw new NoticeException("收货地址地区不正确");
			}
			areaName = area.getFull_name();
			if(StringUtils.isBlank(address)){
				throw new NoticeException("收货地址不能为空");
			}
		}else{
			areaName = null;
			address = null;
		}
		
		RefundDomain refund = orderItem.getRefund();
		if(refund != null){
			if(refund.getRefundStatus() != RefundStatus.refuse){
				throw new NoticeException("该商品已提交申请");
			}
			refund.setCreateDate(new Date());
		}else{
			refund = new RefundDomain();
		}
		
		refund.setRefundNo(SerialNumberUtil.buildRefundSn());
		refund.setRefundStatus(RefundStatus.apply);
		refund.setAddress(address);
		refund.setAreaName(areaName);
		refund.setAreaId(areaId);
		refund.setBatch(orderItem.getBatch());
		refund.setConsignee(consignee);
		refund.setContact(contact);
		refund.setImage(orderItem.getImage());
		refund.setIsChange(isChange);
		//refund.setManufacturerDate(orderItem.getManufacturerDate());
		refund.setProductCode(orderItem.getProductCode());
		refund.setProductName(orderItem.getProductName());
		refund.setQuantity(quantity);
		refund.setSalePrice(orderItem.getSalePrice());
		refund.setSpecification(orderItem.getSpecification());
		refund.setValidDate(orderItem.getValidDate());
		refund.setWeight(orderItem.getWeight());
		refund.setRemark(remark);
		refund.setOrderNo(order.getOrderNo());
		if(isChange){
			refund.setAmount(BigDecimal.ZERO);
		}
		
		persist(refund);
		
		orderItem.setRefund(refund);
		orderItemService.update(orderItem);
		
		RefundLogDomain log = new RefundLogDomain("您的" + (isChange?"换货":"退货") + "单已申请成功，待售后审核中", order.getMember().getUsername(), "客户", refund);
		refundLogService.persist(log);
		
		return refund.getRefundNo();
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void confirm(Long id, BigDecimal amount, String operator) {
		RefundDomain refund = find(id);
		if(refund == null){
			throw new NoticeException("退款单不存在");
		}
		if(refund.getRefundStatus() != RefundStatus.apply){
			throw new NoticeException("退款单状态不正确");
		}
		refund.setRefundStatus(RefundStatus.delivery);
		RefundLogDomain log = new RefundLogDomain("售后审核通过，待您退货中", operator, "系统", refund);
		refundLogService.persist(log);
		update(refund);
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void refuse(Long[] ids, String operator) {
		List<RefundDomain> list = get(ids);
		for(RefundDomain refund : list){
			if(refund.getRefundStatus() == RefundStatus.apply
					|| refund.getRefundStatus() == RefundStatus.delivery){
				refund.setRefundStatus(RefundStatus.refuse);
				update(refund);
				
				RefundLogDomain log = new RefundLogDomain("售后审核不通过，您的" + (refund.getIsChange()?"退货":"换货") + "单被取消", operator, "系统", refund);
				refundLogService.persist(log);
			}
		}
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void approve(Long id, BigDecimal amount, String operator) {
		RefundDomain refund = find(id);
		if(refund == null){
			throw new NoticeException("单据不存在");
		}
		if(refund.getRefundStatus() != RefundStatus.delivery){
			throw new NoticeException((refund.getIsChange()?"退货":"换货") + "单状态不正确");
		}
		refund.setRefundStatus(RefundStatus.confirm);

		RefundLogDomain log = new RefundLogDomain("售后确认收货，待售后" + (refund.getIsChange()?"换货":"退款") + "中", operator, "系统", refund);
		refundLogService.persist(log);
		update(refund);
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void cancel(String refundNo, Long memberId) {
		RefundDomain refund = getRefund(refundNo, memberId);
		if(refund.getRefundStatus() != RefundStatus.apply){
			throw new NoticeException((refund.getIsChange()?"退货":"换货") + "单状态不正确");
		}
		refund.setRefundStatus(RefundStatus.refuse);
		update(refund);
		
		MemberDomain member = memberService.find(memberId);
		
		RefundLogDomain log = new RefundLogDomain("您取消了" + (refund.getIsChange()?"退货":"换货") + "单", member.getUsername(), "客户", refund);
		refundLogService.persist(log);
	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void applyRefundForAdmin(Long[] itemIds, Integer[] quantitys, Boolean isChange, 
			String consignee, Long areaId, String address, String contact, String remark, Long orderId, String operator) {

		if(ArrayUtils.isEmpty(itemIds) || ArrayUtils.isEmpty(quantitys) || itemIds.length != quantitys.length){
			log.error("itemIds="+itemIds+",quantitys="+quantitys);
			throw new NoticeException("申请失败");
		}

		for(int i = 0 ; i < itemIds.length; i++){
			Long itemId = itemIds[i];
			Integer quantity = quantitys[i];

			String areaName = null;
			Finder finder = Finder.create("from OrderItemDomain bean where bean.id =:itemId and bean.order.id=:orderId");
			finder.setParam("itemId", itemId);
			finder.setParam("orderId", orderId);
			Object obj = finder.findUniqueByHQL();

			if(obj == null){
				throw new NoticeException(isChange?"换货商品不存在":"退货商品不存在");
			}
			OrderItemDomain orderItem = (OrderItemDomain) obj;

			if(orderItem.getQuantity() < quantity){
				throw new NoticeException(isChange?"换货数量不正确":"退货数量不存在");
			}

			OrderDomain order = orderItem.getOrder();
			if(order.getOrderStatus() != OrderStatus.waitSellerSendGoods
					&& order.getOrderStatus() != OrderStatus.tradeFinished){
				throw new NoticeException("订单状态不正确");
			}

			if(isChange){
				if(areaId == null){
					throw new NoticeException("收货地址地区不正确");
				}
				AreaDomain area = areaService.find(areaId);
				if(area == null){
					throw new NoticeException("收货地址地区不正确");
				}
				areaName = area.getFull_name();
				if(StringUtils.isBlank(address)){
					throw new NoticeException("收货地址不能为空");
				}
			}else{
				areaName = null;
				address = null;
			}

			RefundDomain refund = orderItem.getRefund();
			if(refund != null){
				if(refund.getRefundStatus() != RefundStatus.refuse){
					throw new NoticeException("该商品已提交申请");
				}
				refund.setCreateDate(new Date());
			}else{
				refund = new RefundDomain();
			}

			refund.setRefundNo(SerialNumberUtil.buildRefundSn());
			refund.setRefundStatus(RefundStatus.apply);
			refund.setAddress(address);
			refund.setAreaName(areaName);
			refund.setAreaId(areaId);
			refund.setBatch(orderItem.getBatch());
			refund.setConsignee(consignee);
			refund.setContact(contact);
			refund.setImage(orderItem.getImage());
			refund.setIsChange(isChange);
			//refund.setManufacturerDate(orderItem.getManufacturerDate());
			refund.setProductCode(orderItem.getProductCode());
			refund.setProductName(orderItem.getProductName());
			refund.setQuantity(quantity);
			refund.setSalePrice(orderItem.getSalePrice());
			refund.setSpecification(orderItem.getSpecification());
			refund.setValidDate(orderItem.getValidDate());
			refund.setWeight(orderItem.getWeight());
			refund.setRemark(remark);
			refund.setOrderNo(order.getOrderNo());
			if(isChange){
				refund.setAmount(BigDecimal.ZERO);
			}

			persist(refund);

			orderItem.setRefund(refund);
			orderItemService.update(orderItem);

			RefundLogDomain log = new RefundLogDomain("您的" + (isChange?"换货":"退货") + "单已申请成功，待售后审核中", operator, "系统", refund);
			refundLogService.persist(log);
		}

	}

	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public void receive(String refundNo, Long memberId) {
		RefundDomain refund = getRefund(refundNo, memberId);
		if(refund.getRefundStatus() != RefundStatus.send){
			throw new NoticeException("换货单状态不正确");
		}
		refund.setRefundStatus(RefundStatus.finish);
		update(refund);
		
		MemberDomain member = memberService.find(memberId);

		OrderDomain order = refund.getOrderItem().getOrder();
		if(order.getAllOrderItemToRefundAndFinished()){
			order.setOrderStatus(OrderStatus.tradeFinished);
			orderService.update(order);

			OrderLogDomain orderLog = new OrderLogDomain();
			orderLog.setOrder(order);
			orderLog.setLogText("换货成功");
			orderLog.setOperatorType("系统");
			orderLog.setOperator(member.getUsername());
			orderLog.setLogType(LogType.rejectFinish);
			orderLogService.persist(orderLog);
		}

		RefundLogDomain log = new RefundLogDomain("您已确认收货，换货完成", member.getUsername(), "客户", refund);
		refundLogService.persist(log);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void finish(Long id, String operator) {
		RefundDomain refund = this.find(id);
		if(refund == null){
			throw new NoticeException("退款单不存在");
		}
		if(refund.getIsChange()){
			throw new NoticeException("退款单无需退款");
		}
		if(refund.getRefundStatus() != RefundStatus.confirm){
			throw new NoticeException("退款单状态不正确");
		}
		refund.setRefundStatus(RefundStatus.finish);
		this.update(refund);

		OrderDomain order = refund.getOrderItem().getOrder();
		if(order.getAllOrderItemToRefundAndFinished()){
			order.setOrderStatus(OrderStatus.tradeClosed);
			orderService.update(order);

			OrderLogDomain orderLog = new OrderLogDomain();
			orderLog.setOrder(order);
			orderLog.setLogText("退货成功");
			orderLog.setOperatorType("系统");
			orderLog.setOperator(operator);
			orderLog.setLogType(LogType.rejectFinish);
			orderLogService.persist(orderLog);
		}

		RefundLogDomain log = new RefundLogDomain("售后已退款，退款完成", operator, "系统", refund);
		refundLogService.persist(log);
	}
}
